home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / textual / tex / files / !tex / TeXsource / commontex / c / expand < prev    next >
Encoding:
Text File  |  1988-04-18  |  18.3 KB  |  471 lines

  1. /*
  2.  *    Copyright 1986, 1987 Pat Joseph Monardo. All rights reserved.
  3.  *    Copying of this file is granted according to the provisions 
  4.  *    specified in the file COPYING which must accompany this file.
  5.  */
  6.  
  7.  
  8. /*
  9.  *              expand.c
  10.  */
  11.  
  12. #include "tex.h"
  13. #include "cmds.h"
  14. #include "heap.h"
  15. #include "io.h"
  16. #include "eq.h"
  17. #include "hash.h"
  18. #include "box.h"
  19. #include "tokenstack.h"
  20. #include "scan.h"
  21. #include "token.h"
  22. #include "tokenlists.h"
  23. #include "cond.h"
  24. #include "file.h"
  25. #include "print.h"
  26. #include "error.h"
  27. #include "expand.h"
  28.  
  29. int             long_state;
  30. ptr             pstack[9];
  31. ptr             cur_mark[5];
  32.  
  33. get_x_token ()
  34. {
  35. restart:
  36.         get_next();
  37.         if (cur_cmd <= MAX_COMMAND)
  38.                 goto done;
  39.         if (cur_cmd >= CALL) {
  40.                 if (cur_cmd < END_TEMPLATE)
  41.                         macro_call();
  42.                 else {
  43.                         cur_cs = FROZEN_ENDV;
  44.                         cur_cmd = ENDV;
  45.                         goto done;
  46.                 }
  47.         } else expand();
  48.         goto restart;
  49.  
  50. done:
  51.         if (cur_cs == 0)
  52.                 cur_tok = cur_cmd * 0400 + cur_chr;
  53.         else cur_tok = CS_TOKEN_FLAG + cur_cs;
  54. }
  55.  
  56. expand ()
  57. {
  58.         int             j;
  59.         ptr             p;
  60.         ptr             q;
  61.         ptr             r;
  62.         hword   t;
  63.         int             save_scanner_status;
  64.         val             cv_backup = cur_val;
  65.         int             radix_backup = radix;
  66.         int             cvl_backup = cur_val_level;
  67.         int             co_backup = cur_order;/*DIFF*/
  68.         ptr             backup_backup = token_link(backup_tokens);      
  69.  
  70.         if (cur_cmd < CALL) {
  71.                 if (tracing_commands > 1)
  72.                         show_cur_cmd_chr();
  73.                 switch (cur_cmd)
  74.                 {
  75.                 case TOP_BOT_MARK:
  76.                         if (cur_mark[cur_chr] != NULL)
  77.                                 begin_token_list(cur_mark[cur_chr], MARK_TEXT);
  78.                         break;
  79.  
  80.                 case EXPAND_AFTER: 
  81.                         get_token();
  82.                         t = cur_tok;
  83.                         get_token();
  84.                         if (cur_cmd > MAX_COMMAND)
  85.                                 expand();
  86.                         else back_input();
  87.                         cur_tok = t;
  88.                         back_input();
  89.                         break;
  90.  
  91.                 case NO_EXPAND:
  92.                         save_scanner_status = scanner_status;
  93.                         scanner_status = NORMAL;
  94.                         get_token(); 
  95.                         scanner_status = save_scanner_status;
  96.                         t = cur_tok;
  97.                         back_input();
  98.                         if (t >= CS_TOKEN_FLAG) {
  99.                                 p = new_token();
  100.                                 token(p) = CS_TOKEN_FLAG + FROZEN_DONT_EXPAND;
  101.                                 token_link(p) = loc;
  102.                                 start = p;
  103.                                 loc = p;
  104.                         }
  105.                         break;
  106.  
  107.                 case CS_NAME:
  108.                         p = r = new_token();
  109.                         do {
  110.                                 get_x_token();
  111.                                 if (cur_cs == 0)
  112.                                         store_new_token(cur_tok);
  113.                         } while (cur_cs == 0);
  114.                         if (cur_cmd != END_CS_NAME) {
  115.                                 print_err("Missing ");
  116.                                 print_esc("endcsname");
  117.                                 print(" inserted");
  118.                                 help_cs();
  119.                                 back_error();
  120.                         }
  121.                         j = first;
  122.                         p = token_link(r);
  123.                         while (p != NULL) {
  124.                                 if (j >= max_buf_stack) {
  125.                                         max_buf_stack = j + 1;
  126.                                         if (max_buf_stack == BUF_SIZE)
  127.                                                 overflow("buffer size", BUF_SIZE);
  128.                                 }
  129.                                 buffer[j] = token(p) % 0400;
  130.                                 incr(j);
  131.                                 p = token_link(p);
  132.                         }
  133.                         if (j > first + 1) {
  134.                                 no_new_control_sequence = FALSE;
  135.                                 cur_cs = id_lookup(first, j - first);
  136.                                 no_new_control_sequence = TRUE;
  137.                         } else if (j == first)
  138.                                 cur_cs = NULL_CS;
  139.                         else cur_cs = SINGLE_BASE + buffer[first];
  140.                         flush_list(r);
  141.                         if (eq_type(cur_cs) == UNDEFINED_CS)
  142.                                 eqtb[cur_cs] = eqtb[FROZEN_RELAX];
  143.                         cur_tok = cur_cs + CS_TOKEN_FLAG;
  144.                         back_input();
  145.                         break;
  146.                 
  147.                 case CONVERT:
  148.                         conv_toks();
  149.                         break;
  150.                 
  151.                 case THE:
  152.                         ins_the_toks();
  153.                         break;
  154.                 
  155.                 case IF_TEST:
  156.                         conditional();
  157.                         break;
  158.                 
  159.                 case FI_OR_ELSE:
  160.                         if (cur_chr > if_limit) {
  161.                                 if (if_limit == IF_CODE) {
  162.                                         insert_relax();
  163.                                 } else {
  164.                                         print_err("Extra ");
  165.                                         print_cmd_chr(FI_OR_ELSE, cur_chr);
  166.                                         help_extra_if();
  167.                                         error();
  168.                                 }
  169.                         } else {
  170.                                 while (cur_chr != FI_CODE)
  171.                                         pass_text();
  172.                                 pop_cond();
  173.                         }
  174.                         break;
  175.  
  176.                 case INPUT:
  177.                         if (cur_chr > 0)
  178.                                 force_eof = TRUE;
  179.                         else if (name_in_progress)
  180.                                 insert_relax();
  181.                         else start_input();
  182.                         break;
  183.                 
  184.                 default:
  185.                         print_err("Undefined control sequence");
  186.                         help_undefd();
  187.                         error();
  188.                         break;
  189.                 }
  190.         } else if (cur_cmd < END_TEMPLATE)
  191.                 macro_call();
  192.         else {
  193.                 cur_tok = CS_TOKEN_FLAG + FROZEN_ENDV;
  194.                 back_input();
  195.         }
  196.         cur_val = cv_backup;
  197.         cur_val_level = cvl_backup;
  198.         radix = radix_backup;
  199.         cur_order = co_backup;/*DIFF*/
  200.         token_link(backup_tokens) = backup_backup;
  201. }
  202.  
  203. insert_relax ()
  204. {
  205.         cur_tok = CS_TOKEN_FLAG + cur_cs;
  206.         back_input();
  207.         cur_tok = CS_TOKEN_FLAG + FROZEN_RELAX;
  208.         back_input();
  209.         token_type = INSERTED;
  210. }
  211.  
  212. #define runaway_arg() \
  213.         {if (long_state == CALL) { \
  214.                 runaway(); \
  215.                 print_err("Paragraph ended before "); \
  216.                 sprint_cs(warning_index); \
  217.                 print(" was complete"); \
  218.                 help_runaway(); \
  219.                 back_error();} \
  220.         pstack[n] = token_link(temp_toks); \
  221.         align_state -= unbalance; \
  222.         for (m = 0; m <= n; incr(m)) \
  223.                 flush_list(pstack[m]); \
  224.         goto local_exit;}
  225.  
  226. macro_call ()
  227. {
  228.         int             m;
  229.         int             n;
  230.         ptr             p;
  231.         ptr             q;
  232.         ptr             r;
  233.         ptr             s;
  234.         ptr             t;
  235.         ptr             u;
  236.         ptr             v;
  237.         ascii   match_chr;
  238.         ptr             ref_count;
  239.         ptr             rbrace_ptr;
  240.         ptr             save_warning_index;
  241.         int             save_scanner_status;
  242.         int             unbalance;
  243.  
  244.         n = 0;
  245.         ref_count = cur_chr;
  246.         r = token_link(ref_count);
  247.         save_scanner_status = scanner_status;
  248.         save_warning_index = warning_index;
  249.         warning_index = cur_cs;
  250.         if (tracing_macros > 0) {
  251.                 begin_diagnostic();
  252.                 print_ln();
  253.                 print_cs(warning_index);
  254.                 token_show(ref_count);
  255.                 end_diagnostic(FALSE);
  256.         }
  257.         if (token(r) != END_MATCH_TOKEN) {
  258.                 scanner_status = MATCHING;
  259.                 unbalance = 0;
  260.                 long_state = eq_type(cur_cs);
  261.                 if (long_state >= OUTER_CALL)
  262.                         long_state -= 2;
  263.                 do {
  264.                         if (token(r) > MATCH_TOKEN + 127 ||
  265.                                 token(r) < MATCH_TOKEN) {
  266.                                 s = NULL;
  267.                         } else {
  268.                                 match_chr = token(r) - MATCH_TOKEN;
  269.                                 s = token_link(r);
  270.                                 r = s;
  271.                                 p = temp_toks;
  272.                                 token_link(p) = NULL;
  273.                                 m = 0;
  274.                         }
  275.  
  276.                 contin:
  277.                         get_token();
  278.                         if (cur_tok == token(r)) {
  279.                                 r = token_link(r);
  280.                                 if (token(r) >= MATCH_TOKEN &&
  281.                                         token(r) <= END_MATCH_TOKEN) {
  282.                                                 if (cur_tok < LEFT_BRACE_LIMIT)
  283.                                                         decr(align_state);
  284.                                                 goto found;
  285.                                 } else goto contin;
  286.                         }
  287.                         if (s != r) {
  288.                                 if (s == NULL) {
  289.                                         print_err("Use of ");
  290.                                         sprint_cs(warning_index);
  291.                                         print(" doesn't match its definition");
  292.                                         help_match();
  293.                                         error();
  294.                                         goto local_exit;
  295.                                 } else {
  296.                                         t = s;
  297.                                         do {
  298.                                                 store_new_token(token(t));
  299.                                                 incr(m);
  300.                                                 u = token_link(t);
  301.                                                 v = s;
  302.                                                 loop {
  303.                                                         if (u == r) {
  304.                                                                 if (cur_tok != token(v))
  305.                                                                         break;
  306.                                                                 else {
  307.                                                                         r = token_link(v);
  308.                                                                         goto contin;
  309.                                                                 }
  310.                                                         }
  311.                                                         if (token(u) != token(v))
  312.                                                                 break;
  313.                                                         u = token_link(u);
  314.                                                         v = token_link(v);
  315.                                                 }
  316.                                                 t = token_link(t);
  317.                                         } while (t != r);
  318.                                         r = s;
  319.                                 }
  320.                         }
  321.                         if (cur_tok == par_token && long_state != LONG_CALL)
  322.                                 runaway_arg();
  323.                         if (cur_tok < RIGHT_BRACE_LIMIT) {
  324.                                 if (cur_tok < LEFT_BRACE_LIMIT) {
  325.                                         unbalance = 1;
  326.                                         loop {
  327.                                                 fast_store_new_token(cur_tok);
  328.                                                 get_token();
  329.                                                 if (cur_tok == par_token && 
  330.                                                         long_state != LONG_CALL) {
  331.                                                         runaway_arg();
  332.                                                 }
  333.                                                 if (cur_tok < RIGHT_BRACE_LIMIT) {
  334.                                                         if (cur_tok < LEFT_BRACE_LIMIT) 
  335.                                                                 incr(unbalance);
  336.                                                         else {
  337.                                                                 decr(unbalance);
  338.                                                                 if (unbalance == 0)
  339.                                                                         break;
  340.                                                         }
  341.                                                 }
  342.                                         }
  343.                                         rbrace_ptr = p;
  344.                                         store_new_token(cur_tok);
  345.                                 } else {
  346.                                         back_input();
  347.                                         print_err("Argument of ");
  348.                                         sprint_cs(warning_index);
  349.                                         print(" has an extra `}'");
  350.                                         help_match_xtra();
  351.                                         incr(align_state);
  352.                                         long_state = CALL;
  353.                                         cur_tok = par_token;
  354.                                         ins_error();
  355.                                 }
  356.                         } else {
  357.                                 if (cur_tok == SPACE_TOKEN &&
  358.                                         token(r) <= END_MATCH_TOKEN &&
  359.                                         token(r) >= MATCH_TOKEN)
  360.                                         goto contin;
  361.                                 store_new_token(cur_tok);
  362.                         }
  363.                         incr(m);
  364.                         if (token(r) > END_MATCH_TOKEN || token(r) < MATCH_TOKEN)
  365.                                 goto contin;
  366.  
  367.                 found:
  368.                         if (s != NULL) {
  369.                                 if (m == 1 &&
  370.                                         token(p) < RIGHT_BRACE_LIMIT &&
  371.                                         p != temp_toks) {
  372.                                         token_link(rbrace_ptr) = NULL;
  373.                                         free_token(p);
  374.                                         p = token_link(temp_toks);
  375.                                         pstack[n] = token_link(p);
  376.                                         free_token(p);
  377.                                 } else pstack[n] = token_link(temp_toks);
  378.                                 incr(n);
  379.                                 if (tracing_macros > 0) {
  380.                                         begin_diagnostic();
  381.                                         print_nl("");
  382.                                         print_char(match_chr);
  383.                                         print_int(n);
  384.                                         print("<-");
  385.                                         show_token_list(pstack[n - 1], NULL, 1000L);
  386.                                         end_diagnostic(FALSE);
  387.                                 }
  388.                         }
  389.                 } while (token(r) != END_MATCH_TOKEN);
  390.         }
  391.         while (state == TOKEN_LIST && loc == NULL)
  392.                 end_token_list();
  393.         begin_token_list(ref_count, MACRO);
  394.         name = warning_index;
  395.         loc = token_link(r);
  396.         if (n > 0) {
  397.                 if (param_ptr + n > max_param_stack) {
  398.                         max_param_stack = param_ptr + n;
  399.                         if (max_param_stack >= PARAM_SIZE)
  400.                                 overflow("parameter stack size", PARAM_SIZE);
  401.                 }
  402.                 for (m = 0; m < n; incr(m))
  403.                         param_stack[param_ptr + m] = pstack[m];
  404.                 param_ptr += n;
  405.         }
  406.  
  407. local_exit:
  408.         scanner_status = save_scanner_status; 
  409.         warning_index = save_warning_index; 
  410. }
  411.  
  412. x_token ()
  413. {
  414.         while (cur_cmd > MAX_COMMAND) {
  415.                 expand();
  416.                 get_next();
  417.         }
  418.         if (cur_cs == 0)
  419.                 cur_tok = cur_cmd * 0400 + cur_chr;
  420.         else cur_tok = CS_TOKEN_FLAG + cur_cs;
  421. }
  422.  
  423. /*
  424.  *      Help text
  425.  */
  426.  
  427. help_runaway ()
  428. {
  429.         help3("I suspect you've forgotten a `}', causing me to apply this",
  430.         "control sequence to too much text. How can we recover?",
  431.         "My plan is to forget the whole thing and hope for the best.");
  432. }
  433.  
  434. help_match ()
  435. {
  436.         help4("If you say, e.g., `\\def\\a1{...}', then you must always",
  437.         "put `1' after `\\a', since control sequence names are",
  438.         "made up of letters only. The macro here has not been",
  439.         "followed by the required stuff, so I'm ignoring it.");
  440. }
  441.  
  442. help_match_xtra ()
  443. {
  444.         help6("I've run across a `}' that doesn't seem to match anything.",
  445.         "For example, `\\def\\a#1{...}' and `\\a}' would produce",
  446.         "this error. If you simply proceed now, the `\\par' that",
  447.         "I've just inserted will cause me to report a runaway",
  448.         "argument that might be the root of the problem. But if",
  449.         "your `}' was spurious, just type `2' and it will go away.");
  450. }
  451.  
  452. help_undefd ()
  453. {
  454.         help5("The control sequence at the end of the top line",
  455.         "of your error message was never \\def'ed. If you have",
  456.         "misspelled it (e.g., `\\hobx'), type `I' and the correct",
  457.         "spelling (e.g., `I\\hbox'). Otherwise just continue,",
  458.         "and I'll forget about whatever was undefined.");
  459. }
  460.  
  461. help_cs ()
  462. {
  463.         help2("The control sequence marked <to be read again> should",
  464.         "not appear between \\csname and \\endcsname.");
  465. }
  466.  
  467. help_extra_if ()
  468. {
  469.         help1("I'm ignoring this; it doesn't match any \\if.");
  470. }
  471.